package com.tt.job.container;

import com.tt.job.api.Job;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import sun.misc.JarFilter;

import java.io.File;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 任务运行容器
 **/
public class JobContainer {
    private final static ConcurrentHashMap<String, JobContainer> containerMap = new ConcurrentHashMap<>();
    private final static Logger logger = LoggerFactory.getLogger(JobContainer.class);
    private final String name;
    private final String packageName;
    private final String path;
    private ClassLoader baseClassLoader = JobContainer.class.getClassLoader();
    private ClassLoader classLoader = null;
    private AnnotationConfigApplicationContext context;

    public JobContainer(String name, String path, String configClass) {
        this.name = name;
        this.path = path;
        this.packageName = configClass;
        String classPath = getClassPath(path);
        try {
            classLoader = ContainerClassLoader.getClassLoader(baseClassLoader, classPath);
            Class<?> annotationClass = classLoader.loadClass(configClass);
            //新建spring容器
            Thread.currentThread().setContextClassLoader(classLoader);
            context = new AnnotationConfigApplicationContext(annotationClass);
            context.setClassLoader(classLoader);
            context.start();
            Thread.currentThread().setContextClassLoader(baseClassLoader);
            logger.info("容器启动成功！ name:{}, path:{}, class:{}", name, path, configClass);
        } catch (Exception e) {
            logger.error("init JobContainer Failed! container:{}", path, e);
        }

    }

    private String getClassPath(String pathString) {
        String[] paths = pathString.split(";");
        StringBuilder classPath = new StringBuilder();
        for (String path : paths) {
            File dir = new File(path);
            File[] jars = dir.listFiles(new JarFilter());
            classPath.append(dir.getAbsolutePath());
            classPath.append(File.pathSeparator);
            if (jars != null) {
                for (File jar : jars) {
                    classPath.append(jar.getAbsolutePath());
                    classPath.append(File.pathSeparator);
                }
            }
        }

        return classPath.toString();
    }

    /**
     * 通过jobClass判断job是托管在哪个container中
     *
     * @param jobClass
     * @return null表示不存在任何container中
     */
    public static JobContainer getContainer(String jobClass) {
        return containerMap.get(jobClass);
    }

    /**
     * 根据class获取job实体对象
     *
     * @param jobClass
     * @return
     */
    public Job getBean(Class<? extends Job> jobClass) {
        return context.getBean(jobClass);
    }

    /**
     * 获取当前容器的classLoader
     *
     * @return
     */
    public ClassLoader getClassLoader() {
        return classLoader;
    }

    public Map<String, Job> getJobMap() {
        Map<String, Job> result = context.getBeansOfType(Job.class);
        // 注册所有业务job到缓存中
        for (Job job : result.values()) {
            containerMap.put(job.getClass().getName(), this);
        }
        return result;
    }

    public String getName() {
        return name;
    }

    public String getPackageName() {
        return packageName;
    }

    public String getPath() {
        return path;
    }
}
